package com.example.demo.heima.reactor;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;

/**
 * ******************************************************
 *
 * @author liugh9
 * @version 1.0
 * @classname Server
 * @description
 * @date 2023/08/12 16:10
 * <p>
 * ******************************************************
 */
public class Server {

    private int port;

    public int getPort() {
        return port;
    }

    // 各线程引用
    // acceptor thread
    private Acceptor acceptor;
    // pollerios threads
    public Set<PollerIO> ioThreads;
    // business threads
    public ExecutorService buExecutor;

    // status flag
    protected volatile boolean stopped = true;

    public void init() {
        // TODO: 2023/8/12 read conf
        this.port = 9999;
        // prepare io thread
        int ioNums = Math.max(4, Runtime.getRuntime().availableProcessors() * 2); // 至少4个
        this.ioThreads = new HashSet<>(ioNums);
        for (int i = 0; i < ioNums; i++) {
            PollerIO ioThread = new PollerIO("poller" + i, this);
            ioThreads.add(ioThread);
        }
        // prepare accept thread
        try {
            this.acceptor = new Acceptor("accept", this, this.ioThreads);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        // start buExecutor
        this.buExecutor = new ThreadPoolExecutor(
                200,
                500,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10000));
        // start ioThreads
        for (PollerIO ioThread : ioThreads) {
            ioThread.start();
        }
        // start acceptor thread
        this.acceptor.start();
    }

    public void shutdown() {
        this.stopped = true;
        this.buExecutor.shutdown();
    }

    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(1);
        Server server = new Server();
        server.init();
        server.start();
        // stop ?
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            server.shutdown();
            latch.countDown();
        }));

        try {
            latch.await();
            System.out.println("server 退出");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void addTask(BusTask task) {
        this.buExecutor.submit(task);
    }
}
